
package com.test;

import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.Advisor;
import org.springframework.aop.IntroductionInterceptor;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultIntroductionAdvisor;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;

// 3. 使用 IntroductionAdvisor 应用引入
public class IntroductionExample {
	public static void main(String[] args) {
		// 1. 创建目标对象
		Person target = new Person();
		// 2. 创建ProxyFactory并设置目标
		ProxyFactory factory = new ProxyFactory(target);
		// 3. 强制使用CGLIB代理，以保证能代理类而不仅仅是接口
		factory.setProxyTargetClass(true);
		// 4. 创建并添加引介切面
		Advisor advisor = new DefaultIntroductionAdvisor(new AnimalIntroductionInterceptor2(), Animal.class);
		factory.addAdvisor(advisor);
		// 5. 获取代理对象
		Object proxy = factory.getProxy();

		// 测试：现在代理对象既是Dog，也是Animal
		Person dog = (Person) proxy;
		System.out.println(dog.getAge()); // 可以调用人类自身的方法

		Animal animal = (Animal) proxy; // 可以强制转换为引入的接口
		animal.eat(); // 可以调用引入的方法
	}
	static class Person {
		private int age;

		public void setAge(int age) {
			this.age = age;
		}

		public int getAge() {
			return age;
		}
	}
	// 要引入的接口
	public interface Animal {
		void eat();
	}

	public static class AnimalIntroductionInterceptor implements IntroductionInterceptor, Animal {

		@Override
		public Object invoke(MethodInvocation invocation) throws Throwable {
			// 判断被拦截的方法是否属于要引入的接口
			if (implementsInterface(invocation.getMethod().getDeclaringClass())) {
				// 如果是引入接口的方法，则调用本拦截器实例上的相应方法
				return invocation.getMethod().invoke(this, invocation.getArguments());
			}
			// 否则，继续执行拦截器链，最终调用目标对象的原有方法
			return invocation.proceed();
		}

		@Override
		public void eat() {
			System.out.println("Animal eat"); // 实现引入接口的方法
		}

		@Override
		public boolean implementsInterface(Class<?> intf) {
			// 判断给定接口是否是要引入的接口
			return intf.isAssignableFrom(Animal.class);
		}
	}
	public static class AnimalIntroductionInterceptor2 extends DelegatingIntroductionInterceptor implements Animal {
		// 只需实现引入接口的方法
		@Override
		public void eat() {
			System.out.println("Animal eat111111");
		}
	}
// 注意：默认情况下，DelegatingIntroductionInterceptor 的 implementsInterface 方法会使用拦截器实例实现的所有接口（除了IntroductionInterceptor类型）作为引入的接口。
}